from FluidClass.FluidSettings import FluidSettings
from abc import ABC, abstractmethod


class ResistanceAbstractClass(ABC):

    def __init__(self, fluid: FluidSettings, length: float = 0, index: int = None):
        self.fluid = fluid
        self.length = length
        self.index = index
        self.type_name = None
        self.params_geom = {}
        self.section = None

    def velocity(self):
        return self.fluid.mass_flow / (self.fluid.density * self.area())

    def reynolds_number(self):
        return self.velocity() * (self.diameter_hydraulic() / self.fluid.get_kinematic_viscosity())

    def velocity_head(self):
        return (self.fluid.density * self.velocity() ** 2) / 2

    def pressure_drop(self):
        return round(self.total_resistance_coefficient() * self.velocity_head(), 1)

    def total_resistance_coefficient(self):
        return round(self.local_resistance_coefficient() + self.frictional_resistance_coefficient(), 3)

    def frictional_resistance_coefficient(self):
        return self.resistance_coefficient_lambda() * (self.length / self.diameter_hydraulic())

    def get_params_element(self) -> dict:
        params_element = dict(
            index=self.index,
            type=self.type_name,
            params_geom=self.get_params_geom(),
            section=self.section,
            velocity=round(self.velocity(), 2),
            reynolds_number=int(round(self.reynolds_number(), 0)),
            total_resistance_coefficient=self.total_resistance_coefficient(),
            pressure_drop=self.pressure_drop()
        )
        return params_element

    def update_fluid(self, new_fluid: FluidSettings):
        self.fluid = new_fluid

    def __str__(self):
        return f'{self.pressure_drop()} Па'

    @abstractmethod
    def area(self):
        """
        Метод определяет площадь проходного сечения элемента
        """

    @abstractmethod
    def diameter_hydraulic(self):
        """
        Метод определяет гидравлический диаметр элемента
        """

    @abstractmethod
    def local_resistance_coefficient(self):
        """
        Метод определяет коэффициент местного сопротивления элемента
        """

    @abstractmethod
    def resistance_coefficient_lambda(self):
        """
        Метод определяет коэффициент сопротивления лямбда
        """

    @abstractmethod
    def get_params_geom(self):
        """
        Метод возвращает словарь с геометрическими параметрами элемента
        """
